﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using Dataweb.NShape;
using Dataweb.NShape.Advanced;
using System.Drawing;
using cz.zcu.PreSti.Components;

namespace cz.zcu.PreSti.Shapes
{
    class OutputSymbol : CircleBase, ISymbol
    {
        protected internal OutputSymbol(ShapeType shapeType, Template template)
            : base(shapeType, template)
        {
        }

        protected internal OutputSymbol(ShapeType shapeType, IStyleSet styleSet)
            : base(shapeType, styleSet)
        {
        }

        public override Shape Clone()
        {
            Shape result = new OutputSymbol(Type, (Template)null);
            result.CopyFrom(this);
            return result;
        }

        public override void CopyFrom(Shape source)
        {
            base.CopyFrom(source);
        }

        protected override Rectangle CalculateBoundingRectangle(bool tight)
        {
            return base.CalculateBoundingRectangle(true);
        }

        protected override bool CalculatePath()
        {
            if (base.CalculatePath())
            {
                Path.Reset();
                int left = (int)Math.Round(-Diameter / 2f);
                int top = (int)Math.Round(-Diameter / 2f);
                int right = left + Diameter;
                Path.StartFigure();
                Path.AddPie(new Rectangle(left, top, Diameter, Diameter), 180 - 45, 270);
                Path.AddPolygon(new PointF[] { new PointF(left, top + Diameter / 2f - connectorWidth), new PointF(left + connectorWidth, top + Diameter / 2f), new PointF(left, top + Diameter / 2f + connectorWidth) });
                Path.AddCurve(new PointF[] { new PointF(4, top), new PointF(0, top + 4), new PointF(-4, top) }, 1);
                Path.CloseFigure();
                return true;
            }
            else return false;
        }

        public override bool HasControlPointCapability(ControlPointId controlPointId, ControlPointCapabilities controlPointCapability)
        {
            switch (controlPointId)
            {
                case 1:
                case 2:
                    return ((controlPointCapability & ControlPointCapabilities.Connect) != 0);
                default:
                    return base.HasControlPointCapability(controlPointId, controlPointCapability);
            }
        }


        protected override int ControlPointCount { get { return 2; } }

        protected override void CalcControlPoints()
        {
            int left = (int)Math.Round(-Diameter / 2f);
            int right = left + Diameter;

            ControlPoints[0].X = left;
            ControlPoints[0].Y = 0;
            ControlPoints[1].X = 0;
            ControlPoints[1].Y = left;
        }

        private int connectorWidth = 5;

        #region ISymbol Members

        public BaseComponent initializeComponent(IPresentation p)
        {
            OutputModel model = (OutputModel)this.ModelObject;
            OutputComponent output = new OutputComponent(p);
            output.Data = model.Data;
            return output;
        }

        public virtual int ActionsCount
        {
            get { return 1; }
        }

        public virtual int EventsCount
        {
            get { return 0; }
        }

        public virtual int SettersCount
        {
            get { return 1; }
        }

        public virtual int GettersCount
        {
            get { return 0; }
        }

        public virtual string GetTitleForAction(int id)
        {
            switch (id)
            {
                case 0:
                    return "Send value to parallel port";
            }
            return null;
        }

        public virtual string GetTitleForEvent(int id)
        {
            return null;
        }

        public string GetTitleForSetter(int id)
        {
            switch (id)
            {
                case 0: return "Data";
            }
            return null;
        }

        public virtual string GetTitleForGetter(int id)
        {
            return null;
        }

        #endregion

        internal static Shape CreateInstance(ShapeType shapeType, Template template)
        {
            return new OutputSymbol(shapeType, template);
        }

    }

    public class OutputModel : ModelObjectBase
    {

        #region Fields

        private byte data;
        private char securityDomainName = 'A';

        private const int PropertyIdData = 1;

        #endregion

        #region properties

        [Category("Presentation")]
        [Description("Data to be sent to the parallel port")]
        [PropertyMappingId(PropertyIdData)]
        public byte Data
        {
            get
            {
                return data;
            }
            set
            {
                data = value;
            }
        }

        #endregion

        public static OutputModel CreateInstance(ModelObjectType modelObjectType) {
			return new OutputModel(modelObjectType);
		}


		protected internal OutputModel(ModelObjectType modelObjectType)
			: base(modelObjectType)
        {
            this.terminalCount = 2;
		}


        protected internal OutputModel(OutputModel source)
			: base(source) {
            Data = source.Data;
            this.terminalCount = 2;
		}


		public override IModelObject Clone() {
            return new OutputModel(this);
		}


		public override IEnumerable<MenuItemDef> GetMenuItemDefs() {
			throw new NotImplementedException();
		}


		public override void Connect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId) {
		}


		public override void Disconnect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId) {
		}

        public override char SecurityDomainName
        {
            get { return securityDomainName; }
            set
            {
                if (value < 'A' || value > 'Z')
                    throw new ArgumentOutOfRangeException("SecurityDomainName", "The domain qualifier has to be an upper case  ANSI letter (A-Z).");
                securityDomainName = value;
            }
        }


        #region IEntity Members

        public static new IEnumerable<EntityPropertyDefinition> GetPropertyDefinitions(int version)
        {
            foreach (EntityPropertyDefinition pi in ModelObjectBase.GetPropertyDefinitions(version))
                yield return pi;
            yield return new EntityFieldDefinition("Data", typeof(byte));
        }

        protected override void LoadFieldsCore(IRepositoryReader reader, int version)
        {
            base.LoadFieldsCore(reader, version);
            Data = reader.ReadByte();
        }

        protected override void SaveFieldsCore(IRepositoryWriter writer, int version)
        {
            base.SaveFieldsCore(writer, version);
            writer.WriteByte(Data);
        }

        #endregion


    }
}
